﻿Imports System.ComponentModel

 
Public Class AlarmDataUploadForm

    Private _pi As ProjectItem

    Private _LoadCancled As Boolean = True

    '当前是否正在上传数据
    Private _isUploading As Boolean = False

    Private _isTest As Boolean = True

    '历史数据的前半页长度（标志）
    Private Const halfPage1 As Byte = 1
    '历史数据的后半页长度（标志）
    Private Const halfPage2 As Byte = 2

    '后台数量上传周期
    Private m_backgroundInteval As Integer = 1 * 1000        '6秒

    Private Sub AlarmDataUploadForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        'Me.btnUpload.Enabled = False

        _pi = MainForm.pi

        LoadTime()

        If LoadAllRef() = False Then
            msg.ShowWarning("无法导入设备,请先配置工程设备")
        End If

    End Sub
    Private Function LoadAllRef() As Boolean
        Dim isDevExist As Boolean = False

        Dim dts As New DevTypeService(_pi)
        Dim rts As New RefTypeService(_pi)

        Me.ListView1.Items.Clear()
        Me.ListView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize)
        Dim item As ListViewItem


        For Each dti As DevTypeItem In dts.GeDevGroupList()   '设备列表
            isDevExist = True
            Dim devlvg As New ListViewGroup(String.Format("{0}号设备", dti.NetId))
            Me.ListView1.Groups.Add(devlvg)
            devlvg.Tag = dti
            For Each rti As RefTypeItem In rts.GeRefGroupList(dti.NetId) '增加该设备冷库信息
                item = New ListViewItem(rti.RefName, devlvg)
                item.Tag = rti
                ListView1.Items.Add(item)
            Next
        Next

        Return isDevExist
    End Function

    Private Sub LoadTime()
        Me.dtpTo.Value = UtilityClass.GetDateString(Now)
        Me.dtpFrom.Value = dtpTo.Value.AddDays(-1).ToLongDateString()
    End Sub



    Protected Overrides Sub OnClosing(ByVal e As System.ComponentModel.CancelEventArgs)
        Me.BackgroundWorker1.CancelAsync()
        Application.DoEvents()
        Me.BackgroundWorker1.Dispose()
        MyBase.OnClosing(e)
    End Sub

    Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
        Me.Close()
    End Sub

    Private Sub btnUpload_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpload.Click
        If Me.btnUpload.Text = "取消" Then
            DoCancel()
            Me.btnUpload.Text = "上传"
            Me.btnExit.Enabled = True

            Me.lblTimeText("")
            Exit Sub
        End If

        If checkValidate() = False Then
            Exit Sub
        End If

        Dim dt As DateTime
        dt = Me.dtpFrom.Value

        Me.btnUpload.Text = "取消"
        Me.btnExit.Enabled = False
        Me.ListView1.Enabled = False
        Me.dtpFrom.Enabled = False
        Me.dtpTo.Enabled = False
        Me.pbUpload.Value = 0
        Me.pbUpload.Visible = True

        Dim i As Integer = 0
        While Me.BackgroundWorker1.IsBusy AndAlso i < 10
            Me.BackgroundWorker1.CancelAsync()
            System.Threading.Thread.Sleep(200)
            Application.DoEvents()
        End While

        If Me.BackgroundWorker1.IsBusy Then
            msg.Show("后台上传操作未结束,请稍后再试")
            Exit Sub
        End If

        Me.BackgroundWorker1.RunWorkerAsync()
    End Sub


    ''' <summary>
    ''' 取消上传
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub DoCancel()
        _LoadCancled = True

        Me.btnUpload.Enabled = False
        Me.lblTimeText("正在取消")

        Me.BackgroundWorker1.CancelAsync()
        Application.DoEvents()
        'Me.BackgroundWorker1.Dispose()

        Me.ListView1.Enabled = True
        Me.dtpFrom.Enabled = True
        Me.dtpTo.Enabled = True
        Me.pbUpload.Visible = False
    End Sub

    ''' <summary>
    ''' 检查输入数据的合法性
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function checkValidate() As Boolean
        Dim tip As String

        '检查时间范围
        If Me.dtpTo.Value <= Me.dtpFrom.Value Then
            tip = "终止时间 必须大于 起始时间。"
            msg.ShowWarning(tip)
            Me.dtpTo.Focus()
            Return False
        End If

        '检查设备是否选择
        Dim bFound As Boolean = False
        For Each item As ListViewItem In Me.ListView1.Items
            If item.Checked Then
                bFound = True
                Exit For
            End If
        Next
        If Not bFound Then
            tip = "请选择要上传历史数据的设备。"
            msg.ShowWarning(tip)
            Me.ListView1.Focus()
            Return False
        End If

        Return True
    End Function

#Region "lblTimeText"

    Private Delegate Sub lblTimeTextHandler(ByVal text As String)

    Private Sub lblTimeText(ByVal text As String)
        If Me.InvokeRequired Then
            Dim d As New lblTimeTextHandler(AddressOf _lblTimeText)
            Me.Invoke(d, New Object() {text})
        Else
            _lblTimeText(text)
        End If
    End Sub

    Private Sub SetUploadTime(ByVal dt As DateTime, ByVal netid As Byte)
        Dim tip As String = String.Format("上传{0}号设备数据,正在上传时间: {1}", netid.ToString(), UtilityClass.GetDateString(dt))
        lblTimeText(tip)
    End Sub

    Private Sub _lblTimeText(ByVal text As String)
        Me.lblTime.Text = text
        Me.lblTime.Refresh()
        Application.DoEvents()
    End Sub

#End Region

    ''' <summary>
    ''' 工作线程运行结束
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        For i As Integer = 1 To 10
            System.Threading.Thread.Sleep(100)
            Application.DoEvents()
        Next

        If Me.lblTime.Text <> "上传结束" Then
            ' Me.lblTimeText("")
        End If

        Me.pbUpload.Visible = False
        Me.btnUpload.Text = "上传"
        Me.btnUpload.Enabled = True
        Me.btnExit.Enabled = True
        Me.ListView1.Enabled = True
        Me.dtpFrom.Enabled = True
        Me.dtpTo.Enabled = True
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        Me.pbUpload.Value = e.ProgressPercentage
    End Sub

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        DoWork(worker)
    End Sub

    ''' <summary>
    ''' 开始后台上传
    ''' </summary>
    ''' <param name="worker"></param>
    ''' <remarks></remarks>
    Private Sub DoWork(ByVal worker As BackgroundWorker)
        Dim dt As DateTime
        dt = Me.dtpFrom.Value

        _LoadCancled = False

        PowerTimeClass.ClearBuffer()

        lblTimeText("")

        Try
#If LSC_DATEUPLOAD_SWICH = "DATE_STARTSTOP_UPLOAD" Then
                        Upload(worker)
#ElseIf LSC_DATEUPLOAD_SWICH = "DATETIME_UPLOAD" Then
            Upload1(worker)

#End If
            ' Upload(worker)
        Catch ex As Exception
            lblTimeText("通讯失败")
            msg.ShowWarning("通讯失败")
            Exit Sub
        End Try

        If worker.CancellationPending Then
            Me.lblTimeText("上传取消")
        Else
            lblTimeText("上传结束")
        End If

    End Sub

    Private Delegate Function GetSelListViewItemHandler() As IList(Of ListViewItem)
    Private Function GetSelListViewItem()
        If Me.InvokeRequired Then
            Dim d As New GetSelListViewItemHandler(AddressOf _GetSelListViewItem)
            Return Me.Invoke(d)
        Else
            Return _GetSelListViewItem()
        End If
    End Function

    Private Function _GetSelListViewItem() As IList(Of ListViewItem)
        Dim m_list As IList(Of ListViewItem) = New List(Of ListViewItem)
        For Each lvi As ListViewItem In Me.ListView1.Items
            If lvi.Checked = True Then
                m_list.Add(lvi)
            End If
        Next
        Return m_list
    End Function

    ''' <summary>
    ''' 上传历史报警记录
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub Upload(ByVal worker As BackgroundWorker)

        Dim cur_netid As Byte
        Dim cur_pid As String
        Dim devtype As Integer

        Dim netidList As IList(Of Byte) = New List(Of Byte)

        netidList.Clear()

        For Each lvi As ListViewItem In GetSelListViewItem()

            cur_netid = CType(lvi.Tag, RefTypeItem).NetId
            cur_pid = CType(lvi.Tag, RefTypeItem).ProjectID

            lblTimeText("正在上传" & lvi.Text & "的报警数据...")

            '过滤掉当前设备中多个选择的冷库的上传过程,一个设备仅仅上传一次数据
            If netidList.Contains(cur_netid) = True Then
                Continue For
            End If

            netidList.Add(cur_netid)

            If worker.CancellationPending Then
                Debug.WriteLine("################" + worker.GetHashCode().ToString() + " Exit0")
                Exit For
            End If

            '当前索引页
            Dim curPageIndex As Integer = -1 '正在写入的报警页号(3751对应0号)
            Dim curRow As Integer = -1 '正在写入的报警的记录号

            '读取历史报警索引页
            Dim dt As DataTable = Nothing

            Try
                dt = AlarmDataClass.GetAlarmIndexPage(cur_netid, curPageIndex, curRow)
            Catch ex As Exception
                Debug.WriteLine(ex.Message)
                Throw ex
            End Try

            Dim dtStart, dtEnd As DateTime
            Dim iPage As Integer
            devtype = DevTypeService.GetdevType(cur_pid, cur_netid)

            '上传当前页
            If dt.Rows.Count > 0 And curPageIndex <> -1 Then  '对无报警存在的情况进行保护
                dtStart = dt.Rows(curPageIndex).Item("StartTime")
                dtEnd = dt.Rows(curPageIndex).Item("EndTime")
                iPage = dt.Rows(curPageIndex).Item("iPage")

                'Dim iResult As Integer

                'If dtEnd > Me.dtpFrom.Value AndAlso dtEnd < Me.dtpTo.Value Then
                If dtStart < Me.dtpTo.Value AndAlso dtEnd > Me.dtpFrom.Value Then
                    Select Case devtype
                        Case 1
                            AlarmDataClass.UpdatePage(cur_pid, cur_netid, iPage, dtStart, dtEnd, curRow)
                        Case 16
                            AlarmDataClass.UpdatePageEx16(cur_pid, cur_netid, iPage, dtStart, dtEnd, curRow)

                    End Select


                    ''上传当前最新页
                    'iResult = AlarmDataClass.CheckAlarmData(cur_pid, cur_netid, iPage, dtStart, dtEnd)
                    'Select Case iResult
                    '    Case -1
                    '        '数据没有上传
                    '        AlarmDataClass.UpdatePage(cur_pid, cur_netid, iPage, dtStart, dtEnd, curRow)
                    '    Case 0
                    '        '数据部分上传
                    '        AlarmDataClass.UpdatePage(cur_pid, cur_netid, iPage, dtStart, dtEnd, curRow)
                    '    Case 1
                    '        '数据已经上传
                    'End Select

                    If worker.CancellationPending Then
                        '取消上传
                        Exit Sub
                    End If

                    Waitfor()
                    '***************************
                End If


                '-----------------------------------
                '计算总进度
                Dim totalProgress As Integer = 0
                Dim currentProgress As Integer = 0
                For ii As Integer = curPageIndex + 1 To dt.Rows.Count - 1
                    dtStart = dt.Rows(ii).Item("StartTime")
                    dtEnd = dt.Rows(ii).Item("EndTime")
                    If dtStart = dtEnd Then
                        '无效的记录
                        Continue For
                    End If
                    If dtStart > Me.dtpTo.Value OrElse dtEnd < Me.dtpFrom.Value Then
                        '不在选择的时间范围内
                        Continue For
                    End If

                    totalProgress += 1
                Next
                For ii As Integer = 0 To curPageIndex - 1
                    dtStart = dt.Rows(ii).Item("StartTime")
                    dtEnd = dt.Rows(ii).Item("EndTime")
                    If dtStart > Me.dtpTo.Value OrElse dtEnd < Me.dtpFrom.Value Then
                        '不在选择的时间范围内
                        Continue For
                    End If

                    totalProgress += 1
                Next
                '------------------------------------


                Dim i As Integer
                '当200页数据已经被循环写入后,读取当前页至第200页之间的所有页数据
                For i = curPageIndex + 1 To dt.Rows.Count - 1

                    If worker.CancellationPending Then
                        '取消上传
                        Exit Sub
                    End If
                    dtStart = dt.Rows(i).Item("StartTime")
                    dtEnd = dt.Rows(i).Item("EndTime")
                    iPage = dt.Rows(i).Item("iPage")

                    SetUploadTime(dtStart, cur_netid)

                    Application.DoEvents()
                    If dtStart = dtEnd Then
                        '无效的记录
                        Continue For
                    End If
                    If dtStart > Me.dtpTo.Value OrElse dtEnd < Me.dtpFrom.Value Then
                        '不在选择的时间范围内
                        Continue For
                    End If

                    'iResult = AlarmDataClass.CheckAlarmData(cur_pid, cur_netid, iPage, dtStart, dtEnd)
                    'If iResult = 1 Then
                    '    '该页已经上传
                    '    Continue For
                    'End If

                    AlarmDataClass.UpdatePage(cur_pid, cur_netid, iPage, dtStart, dtEnd)
                    Waitfor()

                    '报告进度
                    currentProgress += 1
                    Me.BackgroundWorker1.ReportProgress(currentProgress / totalProgress * 100)
                Next

                '读取第一页至当前页之间的所有页面的数据
                For i = 0 To curPageIndex - 1
                    If worker.CancellationPending Then
                        '取消上传
                        Exit Sub
                    End If

                    dtStart = dt.Rows(i).Item("StartTime")
                    dtEnd = dt.Rows(i).Item("EndTime")
                    iPage = dt.Rows(i).Item("iPage")

                    SetUploadTime(dtStart, cur_netid)

                    If dtStart > Me.dtpTo.Value OrElse dtEnd < Me.dtpFrom.Value Then
                        '不在选择的时间范围内
                        Continue For
                    End If

                    'iResult = AlarmDataClass.CheckAlarmData(cur_pid, cur_netid, iPage, dtStart, dtEnd)
                    'If iResult = 1 Then
                    '    '该页已经上传
                    '    Continue For
                    'End If

                    AlarmDataClass.UpdatePage(cur_pid, cur_netid, iPage, dtStart, dtEnd)
                    Waitfor()

                    '报告进度
                    currentProgress += 1
                    Me.BackgroundWorker1.ReportProgress(currentProgress / totalProgress * 100)
                Next
            End If

        Next

    End Sub


    ''' <summary>
    ''' 上传历史报警记录
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub Upload1(ByVal worker As BackgroundWorker)

        Dim cur_netid As Byte
        Dim cur_pid As String
        Dim netidList As IList(Of Byte) = New List(Of Byte)

        netidList.Clear()

        For Each lvi As ListViewItem In GetSelListViewItem()

            cur_netid = CType(lvi.Tag, RefTypeItem).NetId
            cur_pid = CType(lvi.Tag, RefTypeItem).ProjectID

            lblTimeText("正在上传" & lvi.Text & "的报警数据...")

            '过滤掉当前设备中多个选择的冷库的上传过程,一个设备仅仅上传一次数据
            If netidList.Contains(cur_netid) = True Then
                Continue For
            End If

            netidList.Add(cur_netid)

            If worker.CancellationPending Then
                Debug.WriteLine("################" + worker.GetHashCode().ToString() + " Exit0")
                Exit For
            End If

            '当前索引页
            Dim curPageIndex As Integer = -1 '正在写入的报警页号(3751对应0号)
            Dim curRow As Integer = -1 '正在写入的报警的记录号

            '读取历史报警索引页
            Dim dt As DataTable = Nothing

            Try
                dt = AlarmDataClass.GetAlarmIndexPage1(cur_netid, curPageIndex, curRow)
            Catch ex As Exception
                Debug.WriteLine(ex.Message)
                Throw ex
            End Try

            Dim dtStart, dtEnd As DateTime
            Dim iPage As Integer

            '上传当前页
            If dt.Rows.Count > 0 And curPageIndex <> -1 Then  '对无报警存在的情况进行保护
                dtStart = dt.Rows(curPageIndex).Item("StartTime")
                dtEnd = dt.Rows(curPageIndex).Item("EndTime")
                iPage = dt.Rows(curPageIndex).Item("iPage")

                'Dim iResult As Integer

                'If dtEnd > Me.dtpFrom.Value AndAlso dtEnd < Me.dtpTo.Value Then
                If dtStart < Me.dtpTo.Value AndAlso dtEnd > Me.dtpFrom.Value Then
                    AlarmDataClass.UpdatePage1(cur_pid, cur_netid, iPage, dtStart, dtEnd, curRow)

                    ''上传当前最新页
                    'iResult = AlarmDataClass.CheckAlarmData(cur_pid, cur_netid, iPage, dtStart, dtEnd)
                    'Select Case iResult
                    '    Case -1
                    '        '数据没有上传
                    '        AlarmDataClass.UpdatePage(cur_pid, cur_netid, iPage, dtStart, dtEnd, curRow)
                    '    Case 0
                    '        '数据部分上传
                    '        AlarmDataClass.UpdatePage(cur_pid, cur_netid, iPage, dtStart, dtEnd, curRow)
                    '    Case 1
                    '        '数据已经上传
                    'End Select

                    If worker.CancellationPending Then
                        '取消上传
                        Exit Sub
                    End If

                    Waitfor()
                    '***************************
                End If


                '-----------------------------------
                '计算总进度
                Dim totalProgress As Integer = 0
                Dim currentProgress As Integer = 0
                For ii As Integer = curPageIndex + 1 To dt.Rows.Count - 1
                    dtStart = dt.Rows(ii).Item("StartTime")
                    dtEnd = dt.Rows(ii).Item("EndTime")
                    If dtStart = dtEnd Then
                        '无效的记录
                        Continue For
                    End If
                    If dtStart > Me.dtpTo.Value OrElse dtEnd < Me.dtpFrom.Value Then
                        '不在选择的时间范围内
                        Continue For
                    End If

                    totalProgress += 1
                Next
                For ii As Integer = 0 To curPageIndex - 1
                    dtStart = dt.Rows(ii).Item("StartTime")
                    dtEnd = dt.Rows(ii).Item("EndTime")
                    If dtStart > Me.dtpTo.Value OrElse dtEnd < Me.dtpFrom.Value Then
                        '不在选择的时间范围内
                        Continue For
                    End If

                    totalProgress += 1
                Next
                '------------------------------------


                Dim i As Integer
                '当200页数据已经被循环写入后,读取当前页至第200页之间的所有页数据
                For i = curPageIndex + 1 To dt.Rows.Count - 1

                    If worker.CancellationPending Then
                        '取消上传
                        Exit Sub
                    End If
                    dtStart = dt.Rows(i).Item("StartTime")
                    dtEnd = dt.Rows(i).Item("EndTime")
                    iPage = dt.Rows(i).Item("iPage")

                    SetUploadTime(dtStart, cur_netid)

                    Application.DoEvents()
                    If dtStart = dtEnd Then
                        '无效的记录
                        Continue For
                    End If
                    If dtStart > Me.dtpTo.Value OrElse dtEnd < Me.dtpFrom.Value Then
                        '不在选择的时间范围内
                        Continue For
                    End If

                    'iResult = AlarmDataClass.CheckAlarmData(cur_pid, cur_netid, iPage, dtStart, dtEnd)
                    'If iResult = 1 Then
                    '    '该页已经上传
                    '    Continue For
                    'End If

                    AlarmDataClass.UpdatePage1(cur_pid, cur_netid, iPage, dtStart, dtEnd)
                    Waitfor()

                    '报告进度
                    currentProgress += 1
                    Me.BackgroundWorker1.ReportProgress(currentProgress / totalProgress * 100)
                Next

                '读取第一页至当前页之间的所有页面的数据
                For i = 0 To curPageIndex - 1
                    If worker.CancellationPending Then
                        '取消上传
                        Exit Sub
                    End If

                    dtStart = dt.Rows(i).Item("StartTime")
                    dtEnd = dt.Rows(i).Item("EndTime")
                    iPage = dt.Rows(i).Item("iPage")

                    SetUploadTime(dtStart, cur_netid)

                    If dtStart > Me.dtpTo.Value OrElse dtEnd < Me.dtpFrom.Value Then
                        '不在选择的时间范围内
                        Continue For
                    End If

                    'iResult = AlarmDataClass.CheckAlarmData(cur_pid, cur_netid, iPage, dtStart, dtEnd)
                    'If iResult = 1 Then
                    '    '该页已经上传
                    '    Continue For
                    'End If

                    AlarmDataClass.UpdatePage1(cur_pid, cur_netid, iPage, dtStart, dtEnd)
                    Waitfor()

                    '报告进度
                    currentProgress += 1
                    Me.BackgroundWorker1.ReportProgress(currentProgress / totalProgress * 100)
                Next
            End If

        Next

    End Sub

    Private Sub Waitfor()
        System.Threading.Thread.Sleep(200)

        '其它地方正在修改参数或者前台上传时暂停后台上传
        'While g_busy
        '   System.Threading.Thread.Sleep(100)
        'End While

    End Sub



    ''' <summary>
    ''' 读取指定页的数据
    ''' </summary>
    ''' <param name="netID">PLC站号</param>
    ''' <param name="iPage">页地址</param>
    ''' <param name="tryCount">读取数据失败时,连续尝试读取得此时</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function UploadOnePage(ByVal netID As Integer, ByVal iPage As Integer, ByVal tryCount As Integer) As Byte()
        If tryCount < 1 Then
            tryCount = 1
        End If

        Dim buf(512) As Byte
        Dim b1() As Byte = Nothing

        Dim iTry As Integer

        '读取前半页
        iTry = 1
        While b1 Is Nothing AndAlso iTry <= tryCount
            iTry += 1
            b1 = COMHelper.Instance.Send4Byte(netID, FunctionCode.WordWrite, iPage, 256)
        End While
        If b1 Is Nothing Then
            Return Nothing
        End If
        b1.CopyTo(buf, 0)

        '读取前后页
        iTry = 1
        While b1 Is Nothing AndAlso iTry <= tryCount
            iTry += 1
            b1 = COMHelper.Instance.Send4Byte(netID, FunctionCode.WordWrite, iPage, 256)
        End While
        If b1 Is Nothing Then
            Return Nothing
        End If
        b1.CopyTo(buf, 256)

        Return buf
    End Function


    ''' <summary>
    ''' 判断指定位是否为1
    ''' </summary>
    ''' <param name="b"></param>
    ''' <param name="i"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetBit(ByVal b As Byte, ByVal i As Integer) As Byte
        Dim iTest As Byte
        iTest = 2 ^ i

        Dim result As Byte
        result = b And iTest

        If result > 0 Then
            result = 1
        End If

        Return result
    End Function

End Class



